<!doctype html>
<html>
  <head>
    <meta
      http-equiv="Content-Security-Policy"
      content="
			default-src 'none';
			child-src 'self' data: blob:;
			script-src 'self' 'unsafe-eval' 'sha256-wcyBKoCmWZKhgCst5mhUmyU9D+kbbP324A2jWi+2fYs=' https:;
			connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"
    />
  </head>
  <body>
    <script>
      ;(function () {
        const searchParams = new URL(document.location.href).searchParams
        const vscodeWebWorkerExtHostId =
          searchParams.get("vscodeWebWorkerExtHostId") || ""
        const name = searchParams.get("debugged")
          ? "DebugWorkerExtensionHost"
          : "WorkerExtensionHost"
        const parentOrigin = searchParams.get("parentOrigin") || window.origin
        const salt = searchParams.get("salt")

        ;(async function () {
          const hostnameValidationMarker = "v--"
          const hostname = location.hostname
          if (!hostname.startsWith(hostnameValidationMarker)) {
            // validation not requested
            return start()
          }
          if (!crypto.subtle) {
            // cannot validate, not running in a secure context
            return sendError(new Error(`Cannot validate in current context!`))
          }

          // Here the `parentOriginHash()` function from `src/vs/base/browser/iframe.ts` is inlined
          // compute a sha-256 composed of `parentOrigin` and `salt` converted to base 32
          /** @type {string} */
          let parentOriginHash
          try {
            const strData = JSON.stringify({ parentOrigin, salt })
            const encoder = new TextEncoder()
            const arrData = encoder.encode(strData)
            const hash = await crypto.subtle.digest("sha-256", arrData)
            const hashArray = Array.from(new Uint8Array(hash))
            const hashHex = hashArray
              .map((b) => b.toString(16).padStart(2, "0"))
              .join("")
            // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32
            parentOriginHash = BigInt(`0x${hashHex}`)
              .toString(32)
              .padStart(52, "0")
          } catch (err) {
            return sendError(
              err instanceof Error ? err : new Error(String(err)),
            )
          }

          const requiredSubdomain = `${hostnameValidationMarker}${parentOriginHash}.`
          if (
            hostname.substring(0, requiredSubdomain.length) ===
            requiredSubdomain
          ) {
            // validation succeeded!
            return start()
          }

          return sendError(
            new Error(`Expected '${requiredSubdomain}' as subdomain!`),
          )
        })()

        function sendError(error) {
          window.parent.postMessage(
            {
              vscodeWebWorkerExtHostId,
              error: {
                name: error ? error.name : "",
                message: error ? error.message : "",
                stack: error ? error.stack : [],
              },
            },
            "*",
          )
        }

        function start() {
          try {
            let workerUrl = "../../../../base/worker/workerMain.js"
            if (globalThis.crossOriginIsolated) {
              workerUrl += "?vscode-coi=2" // COEP
            }

            const worker = new Worker(workerUrl, { name })
            worker.postMessage("vs/workbench/api/worker/extensionHostWorker")
            const nestedWorkers = new Map()

            worker.onmessage = (event) => {
              const { data } = event

              if (data?.type === "_newWorker") {
                const { id, port, url, options } = data
                const newWorker = new Worker(url, options)
                newWorker.postMessage(port, [port])
                newWorker.onerror = console.error.bind(console)
                nestedWorkers.set(id, newWorker)
              } else if (data?.type === "_terminateWorker") {
                const { id } = data
                if (nestedWorkers.has(id)) {
                  nestedWorkers.get(id).terminate()
                  nestedWorkers.delete(id)
                }
              } else {
                worker.onerror = console.error.bind(console)
                window.parent.postMessage(
                  {
                    vscodeWebWorkerExtHostId,
                    data,
                  },
                  parentOrigin,
                  [data],
                )
              }
            }

            worker.onerror = (event) => {
              console.error(event.message, event.error)
              sendError(event.error)
            }

            self.onmessage = (event) => {
              if (event.origin !== parentOrigin) {
                return
              }
              worker.postMessage(event.data, event.ports)
            }
          } catch (err) {
            console.error(err)
            sendError(err)
          }
        }
      })()
    </script>
  </body>
</html>
